<?php

/**
 * Библиотека функций ядра.
 *
 */
abstract class Kernel {

    /**
     * Абстрактная фабрика. Создает объект указанного типа из указанного "пэкиджа".
     *
     * @param   string  $package
     * @param   string  $type
     * @param   mixed   $arg1[, mixed  $arg2, …]
     * @return  object
     * @throws  Kernel_Filter_Exception_NotFound
     */
    static public function factory($package, $type) {
        $type = str_camelize($type);
        $class = false === strpos($package, '%')
            ? $package . '_' . $type : sprintf($package, $type);
        try {
            Zend_Loader::loadClass($class);
        } catch (Zend_Exception $e) {
            throw new Kernel_Filter_Exception_NotFound($e->getMessage());
        }
        $args = array_slice(func_get_args(), 2);
        // ReflectionClass::newInstanceArgs() появился только в PHP 5.1.3, плюс
        // ко всему, он ругается при создании объекта класса, у которого явно не
        // объявлен конструктор. это — более универсальный вариант :|
        return call_user_func_array(array(new ReflectionClass($class), 'newInstance'), $args);
    }

    /**
     * Возвращает массив наименований классов пэкиджа за исключением 'Abstract'.
     *
     * @param   string  $package
     * @param   boolean $names
     * @return  array
     */
    static public function getClasses($package, $names = false) 
    {
        $PHP_EXT = 'php';
        
        $classes = array();
        $prefix = str_replace(DIRECTORY_SEPARATOR, '_', $package);
        foreach (array(KERNEL_REPOSITORY, PROJECT_REPOSITORY) as $dir) {
            $pattern = $dir . DIRECTORY_SEPARATOR . $package . DIRECTORY_SEPARATOR . '*.' . $PHP_EXT;
            foreach (glob($pattern) as $file) {
                // :KLUDGE: dV 25072008 
                // The PATHINFO_FILENAME constant was added since PHP version 5.2.0
                // So we are forced to use basename as we helpless at our clients stupidity :)
                if ('Abstract' != ($class = basename($file, '.' . $PHP_EXT))) {
                    $classes[] = !$names ? $prefix . '_' . $class : strtolower($class);
                }
            }
        }
        return array_unique($classes);
    }
}
